package com.tnf.bc.bground.service.impl;

import com.alibaba.fastjson.JSON;
import com.tnf.bc.bground.certificate.pojo.LoginUser;
import com.tnf.bc.bground.certificate.pojo.SysUser;
import com.tnf.bc.bground.common.exception.BookSysException;
import com.tnf.bc.bground.common.utils.beanutils.RegularUtils;
import com.tnf.bc.bground.common.utils.jwtutils.JwtTokenUtil;
import com.tnf.bc.bground.common.utils.resultutil.ApiResponse;
import com.tnf.bc.bground.dao.RoleDao;
import com.tnf.bc.bground.dao.UserDao;
import com.tnf.bc.bground.service.iface.LoginService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @description: //登录实现
 * @author: lzl
 * @create: 2022-11-19 09:21
 **/
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    public static final String LOIN_USER_ID = "login_user_";

    public static final String ORDINARY_ROLE_ID = "002";

    public static final String ADMIN_ROLE_ID = "001";

    @Autowired
    private UserDao userDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public ApiResponse login(SysUser user) {
        //AuthenticationManager authentication 进行用户认证
        Map<String, String> map = new HashMap<>();
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassWord());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("用户认证失败");
        }
        LoginUser principal = (LoginUser) authenticate.getPrincipal();
        String userInfo = JSON.toJSONString(principal);
        String userId = principal.getSysUser().getId().toString();
        String jwt = JwtTokenUtil.generateToken(userId);
        map.put("token", jwt);
        redisTemplate.opsForValue().set(LOIN_USER_ID + userId, userInfo,7200000L, TimeUnit.MILLISECONDS);
        return new ApiResponse(200,"登录成功", map);
    }

    @Override
    public ApiResponse logout() {
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        SysUser sysUser = (SysUser) authentication.getPrincipal();
        redisTemplate.delete(LOIN_USER_ID + sysUser.getId());
        return new ApiResponse();
    }

    @Transactional
    @Override
    public ApiResponse register(SysUser user) {
        SysUser sysUser = userDao.selectByUserName(user.getUserName());
        if (!Objects.isNull(sysUser)) {
            throw new BookSysException(ApiResponse.Status.NOTUSER);
        }
        if (!user.getPassWord().matches(RegularUtils.patternStr2)) {
            throw new BookSysException(ApiResponse.Status.PASSWORDRULESERORRTWO);
        }
        //加密后数据
        String encode = passwordEncoder.encode(user.getPassWord());
        user.setPassWord(encode);
        //TODO
        userDao.save(user);
        SysUser registerUser = userDao.selectByUserName(user.getUserName());
        if (!user.getAdmin()) {
            roleDao.selectByCode(ORDINARY_ROLE_ID)
                    .forEach( roleId -> userDao.saveUserRoleRelation(registerUser.getId(), roleId));
        } else {
            roleDao.selectByCode(ADMIN_ROLE_ID)
                    .forEach( roleId -> userDao.saveUserRoleRelation(registerUser.getId(), roleId));
        }
        if (!Objects.isNull(registerUser)) {
            return ApiResponse.ofStatus(ApiResponse.Status.SUCCESS);
        }
        return ApiResponse.ofMessage(500, "系统异常，用户注册失败");
    }
}